﻿using System;
using System.Xml;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

public class ProjectAnalyzeHelper
{
	public static void AnalyzeProject(string proPath, string proType, ref ProjectInfoClass proInf, bool bWrite = false)
    {
        if (proType == "C#工程文件")
        {
            if (!bWrite)
                AnalyzeCSharpProject(proPath, ref proInf);
            else
                WriteCSharpVersion(proPath, ref proInf);
        }
    }

    private static void AnalyzeCSharpProject(string proPath, ref ProjectInfoClass proInfo)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(proPath);
        XmlNodeList xnl = doc.ChildNodes[0].ChildNodes;
        if (doc.ChildNodes[0].Name.ToLower() != "project")
            xnl = doc.ChildNodes[1].ChildNodes;

        string assemblyName = string.Empty;//主程序名称
        string appdesignerfolder = string.Empty;
        string releasePath = string.Empty;  //程序Release路径
        string iconName = string.Empty; //程序的图标
        string outputType = string.Empty;   //工程输出程序类型
                
        foreach (XmlNode xn in xnl)
        {
            if (xn.ChildNodes.Count > 0 && xn.ChildNodes[0].Name.ToLower() == "configuration")
            {
                foreach (XmlNode cxn in xn.ChildNodes)
                {                    
                    if (cxn.Name.ToLower() == "assemblyname")
                    {
                        assemblyName = cxn.InnerText;
                    }
                    if (cxn.Name.ToLower() == "appdesignerfolder")
                    {
                        appdesignerfolder = cxn.InnerText;
                    }
                    if (cxn.Name.ToLower() == "outputtype")
                    {
                        outputType = cxn.InnerText;
                    }
                }
            }
            if (xn.ChildNodes.Count > 0 && xn.Attributes.Count > 0 && xn.Attributes[0].InnerText.ToLower().IndexOf("release") > 0)
            {
                foreach (XmlNode cxn in xn.ChildNodes)
                {
                    if (cxn.Name.ToLower() == "outputpath")
                    {
                        releasePath = cxn.InnerText;
                        break;
                    }
                }
            }
            if (xn.ChildNodes.Count > 0 && xn.ChildNodes[0].Name.ToLower() == "applicationicon")
            {
                foreach (XmlNode cxn in xn.ChildNodes)
                {
                    if (cxn.Name.ToLower() == "applicationicon")
                    {
                        iconName = cxn.InnerText;
                        break;
                    }
                }
            }
            if (xn.ChildNodes.Count > 0 && xn.Name.ToLower() == "itemgroup")
            {
                foreach (XmlNode cxn in xn.ChildNodes)
                {
                    if (cxn.Attributes.Count > 0 && cxn.Attributes[0].InnerText.IndexOf(appdesignerfolder) > -1)
                    {
                        appdesignerfolder = cxn.Attributes[0].InnerText;
                        break;
                    }
                }

            }
        }

        proInfo.pAssemblyInfo = appdesignerfolder;
        if (outputType.ToLower() == "winexe")
        {
            assemblyName += ".exe";
        }
        else if (outputType.ToLower() == "library")
        {
            assemblyName += ".dll";
        }
        proInfo.pAssemblyName = assemblyName;
        proInfo.pIconName = iconName;
        proInfo.pReleaseFolder = releasePath.EndsWith("\\") ? releasePath.Substring(0, releasePath.LastIndexOf("\\")) : releasePath;
        string path = proInfo.pFullPath.Substring(0,proInfo.pFullPath.LastIndexOf("\\"));
        path += "\\" + proInfo.pAssemblyInfo;
        string ver = GetCSharpVersion(path, proInfo.pVersion);
        proInfo.pVersion = ver;
    }

    private static void WriteCSharpVersion(string proPath, ref ProjectInfoClass proInfo)
    {
        string path = proInfo.pFullPath.Substring(0, proInfo.pFullPath.LastIndexOf("\\"));
        path += "\\" + proInfo.pAssemblyInfo;
        string assemblyinfo = string.Empty;
        using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
        {
            assemblyinfo = sr.ReadToEnd();
            string reg = @"AssemblyFileVersion\(""(?<version>.+)""\)";
            string fileVersion =
                Regex.Match(assemblyinfo, reg, RegexOptions.RightToLeft).Groups["version"].Value;
            reg = @"AssemblyVersion\(""(?<version>.+)""\)";
            string assemblyVersion =
                Regex.Match(assemblyinfo, reg,RegexOptions.RightToLeft).Groups["version"].Value;
            string[] versions = proInfo.pVersion.Split('.');
            string[] fVersions = fileVersion.Split('.');
            string[] aVersions = assemblyVersion.Split('.');
            int nSize = Math.Max(fVersions.Length, versions.Length);
            for (int i = 0; i < nSize; ++i)
            {
                if (fVersions[i] != "*")
                {
                    if (versions.Length > i)
                        fileVersion = fileVersion.Replace(fVersions[i], versions[i]);
                }
                else
                {
                    break;
                }
            }
            nSize = Math.Max(aVersions.Length, versions.Length);
            for (int i = 0; i < nSize; ++i)
            {
                if (aVersions[i] != "*")
                {
                    if (versions.Length > i)
                        assemblyVersion = assemblyVersion.Replace(aVersions[i], versions[i]);
                }
                else
                {
                    break;
                }
            }

            assemblyinfo = Regex.Replace(assemblyinfo, @"AssemblyFileVersion\("".+""\)",
                            string.Format("AssemblyFileVersion(\"{0}\")", fileVersion));
            assemblyinfo = Regex.Replace(assemblyinfo, @"AssemblyVersion\("".+""\)",
                            string.Format("AssemblyVersion(\"{0}\")", assemblyVersion));            
        }
        if ( ! string.IsNullOrEmpty(assemblyinfo))
        {
            using (StreamWriter sw = new StreamWriter(path, false, Encoding.Default))
            {
                sw.Write(assemblyinfo);
            }
        }        
    }

    /// <summary>
    /// 获取版本号
    /// 1.如果版本号中没有*,则使用当前版本号
    /// 2.如果版本号中有*，则若*之前的版本相同，则使用老版本，若*之前版本不同则使用当前版本
    /// </summary>
    /// <param name="assemblyPath"></param>
    /// <param name="oldVersion"></param>
    /// <returns></returns>
    private static string GetCSharpVersion(string assemblyPath, string oldVersion)
    {
        using (StreamReader sr = new StreamReader(assemblyPath, Encoding.UTF8))
        {
            string assemblyinfo = sr.ReadToEnd();
            string currentVersion =
                Regex.Match(assemblyinfo, @"AssemblyFileVersion\(""(?<version>.+)""\)",RegexOptions.RightToLeft).Groups["version"].Value;
            if (currentVersion.IndexOf('*') > 0)
            {
                if (!string.IsNullOrEmpty(oldVersion))
                {
                    var cVers = currentVersion.Split('.');
                    var oVers = oldVersion.Split('.');
                    bool bIsSame = true;
                    for (int i = 0; i < cVers.Length; ++i)
                    {
                        if (cVers[i] != "*")
                        {
                            if (oVers.Length > i)
                            {
                                if (int.Parse(cVers[i]) != int.Parse(oVers[i]))
                                {
                                    bIsSame = false;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    if (bIsSame)
                        currentVersion = oldVersion;
                    else
                        currentVersion = currentVersion.Replace('*', '0');
                }
                else
                {
                    currentVersion = currentVersion.Replace('*', '0');
                }
            }            
            
            return currentVersion;
        }
    }
}
